﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Hammock.Web;
using Harvest.Api.ExtensionMethods;
using Harvest.Api.Interfaces;
using Harvest.Api.Model;
using Harvest.Api.Model.Internal;

namespace Harvest.Api
{

    /// <summary>
    /// 
    /// </summary>
    public class ExpensesRepository : RepositoryBase
    {

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="provider">The RestRequestProvider for connecting to the service.</param>
        public ExpensesRepository(IRestRequestProvider provider) :
            base(provider) { }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Expense GetById(int id)
        {

            if (id <= 0) throw new ArgumentOutOfRangeException();

            var client = GetRestClient();
            var request = Provider.RestRequest;
            request.Path = "expenses/" + id;
            request.Method = WebMethod.Get;

            var response = client.Request<ExpenseItem>(request);

            var statusCode = response.StatusCode;
            if (statusCode == HttpStatusCode.NotFound) throw new KeyNotFoundException();

            var result = response.ContentEntity;

            return result.ToExpense();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="updatedSince"></param>
        /// <returns></returns>
        public List<Expense> GetAll()
        {

            var client = GetRestClient();
            var request = Provider.RestRequest;
            request.Path = "expenses";
            request.Method = WebMethod.Get;
            var response = client.Request<Expenses>(request);

            var statusCode = response.StatusCode;
            if (statusCode == HttpStatusCode.NotFound) throw new KeyNotFoundException();

            var result = response.ContentEntity.ExpenseArray.ToList();

            return result.ToExpenses();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public Expense Add(Expense entity)
        {

            if (entity == null) throw new ArgumentNullException();
            //if (entity.Name.IsNullOrEmpty()) throw new ArgumentNullException();

            var client = GetRestClient();
            var request = Provider.RestRequest;
            request.Path = "expenses";
            request.Method = WebMethod.Post;
            request.Entity = entity.ToExpenseItem();

            var response = client.Request(request);

            var statusCode = response.StatusCode;
            if (statusCode == HttpStatusCode.BadRequest) throw new InvalidOperationException();

            var locationHeader = response.Headers["Location"];
            var id = int.Parse(locationHeader.Substring(locationHeader.LastIndexOf(@"/") + 1));

            var result = GetById(id);

            return result;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        public void Remove(int id)
        {

            if (id <= 0) throw new ArgumentOutOfRangeException();

            var client = GetRestClient();
            var request = Provider.RestRequest;
            request.Path = "expenses/" + id;
            request.Method = WebMethod.Delete;
            var response = client.Request(request);

            var statusCode = response.StatusCode;
            if (statusCode == HttpStatusCode.BadRequest) throw new InvalidOperationException();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        public void Remove(Expense entity)
        {

            if (entity == null) throw new ArgumentNullException();
            if (!entity.Id.HasValue) throw new ArgumentNullException();

            Remove(entity.Id.Value);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public Expense Update(Expense entity)
        {

            if (entity == null) throw new ArgumentNullException();
            if (!entity.Id.HasValue) throw new ArgumentNullException();
            //if (entity.Name.IsNullOrEmpty()) throw new ArgumentNullException();

            var client = GetRestClient();
            var request = Provider.RestRequest;
            request.Path = "expenses/" + entity.Id.Value;
            request.Method = WebMethod.Put;
            request.Entity = entity.ToExpenseItem();

            var response = client.Request(request);

            var statusCode = response.StatusCode;
            if (statusCode == HttpStatusCode.BadRequest) throw new InvalidOperationException();

            var locationHeader = response.Headers["Location"];
            var id = int.Parse(locationHeader.Substring(locationHeader.LastIndexOf(@"/") + 1));

            var result = GetById(id);

            return result;

        }


        public void AttachImage()
        {
            throw new NotImplementedException();
        }


        public object GetImage(Expense entity)
        {
            throw new NotImplementedException();
        }

    }

}
